﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Principal;
using System.Text;
using Comdiv.QWeb.Factory;
using Comdiv.QWeb.Security;
using NUnit.Framework;

namespace Comdiv.QWeb.Test.Security
{
	[TestFixture]
	public class authorizer_test
	{
		class fixedPrincipalSource : IPrincipalSource {
			private GenericPrincipal principal;
			public fixedPrincipalSource(string username,string role = "DEFAULT") {
				this.principal = new GenericPrincipal(new GenericIdentity(username), new[] {role});
			}
			public IPrincipal CurrentUser {
				get { return principal; }
			}

			public void SetCurrentUser(IPrincipal logonUser) {
				
			}
		}

		class action_with_role_resolver : IAction, IRoleResolver {
			public object Process(QWebContext context) {
				throw new NotImplementedException();
			}

			public bool IsInRole(IPrincipal principal, string role,bool exact, QWebContext context) {
				if (principal.Identity.Name.Contains("NO")) return false;
				return role == "YES";

			}
		}

		[Test]
		public void uses_custom_role_resolution_on_action() {
			var reg = new QWebServiceRegistry();
			reg.PrincipalSource = new fixedPrincipalSource("test\\NO","YES");
			var auth = reg.GetNew<IActionAuthorizer>();
			var ctx = new QWebContext();
			ctx.Uri = new Uri("http://authcontext/test/sample.qweb");
			ctx.ActionDescriptor = new ActionDescriptor { Role = "YES", Name = "sample.test", Action =  new action_with_role_resolver()};
			ctx.RenderDescriptor = new RenderDescriptor() { Role = "DEFAULT", UseAuthorization = false, OverrideActionAuthorization = false };
			var result = auth.Authorize(ctx);
			Assert.AreEqual(false, result.Authorized);
		}


		[Test]
		public void uses_custom_role_resolution_yes_action()
		{
			var reg = new QWebServiceRegistry();
			reg.PrincipalSource = new fixedPrincipalSource("test\\YES", "YES");
			var auth = reg.GetNew<IActionAuthorizer>();
			var ctx = new QWebContext();
			ctx.Uri = new Uri("http://authcontext/test/sample.qweb");
			ctx.ActionDescriptor = new ActionDescriptor { Role = "YES", Name = "sample.test",Action = new action_with_role_resolver()};
			ctx.RenderDescriptor = new RenderDescriptor() { Role = "DEFAULT", UseAuthorization = false, OverrideActionAuthorization = false };
			var result = auth.Authorize(ctx);
			Assert.AreEqual(true, result.Authorized);
		}


		void test(string renderRole, string actionRole, bool useRenderAuth, bool overrideActionAuth, string role, bool isauth) {
			var reg = new QWebServiceRegistry();
			reg.PrincipalSource = new fixedPrincipalSource("test\\" + role, role);
			var auth = reg.GetNew<IActionAuthorizer>();
			var ctx = new QWebContext();
			ctx.Uri = new Uri("http://authcontext/test/sample.qweb");
			ctx.ActionDescriptor = new ActionDescriptor {Role = actionRole, Name = "sample.test"};
			ctx.RenderDescriptor = new RenderDescriptor() { Role = renderRole, UseAuthorization = useRenderAuth, OverrideActionAuthorization = overrideActionAuth};
			var result = auth.Authorize(ctx);
			Assert.AreEqual(isauth,result.Authorized);
		}

		[Test]
		public void default_role_match_default_action() {
			test("","DEFAULT",false,false,"DEFAULT",true);
		}

		[Test]
		public void render_updagrade_security()
		{
			test("ADMIN", "DEFAULT", true, false, "DEFAULT", false);
		}



		[Test]
		public void render_use_auth_works()
		{
			test("ADMIN", "DEFAULT", false, false, "DEFAULT", true);
		}
		[Test]
		public void default_role_not_match_admin_action()
		{
			test("", "ADMIN", false, false, "DEFAULT", false);
		}

		[Test]
		public void special_actiondomain_role_match_admin_action()
		{
			test("", "ADMIN", false, false, "SAMPLE_ALL", true);
		}

		[Test]
		public void special_actionfullname_role_match_admin_action()
		{
			test("", "ADMIN", false, false, "SAMPLE_TEST", true);
		}

		[Test]
		public void special_not_mathched_actionfullname_role_not_match_admin_action()
		{
			test("", "ADMIN", false, false, "SAMPLE_NOTEST", false);
		}
		[Test]
		public void render_down_grade_security()
		{
			test("DEFAULT", "ADMIN", true, true, "DEFAULT", true);
		}

		[Test]
		public void admin_role_match_default_action()
		{
			test("", "DEFAULT", false, false, "ADMIN", true);
		}
		[Test]
		public void admin_role_match_admin_action()
		{
			test("", "ADMIN", false, false, "ADMIN", true);
		}
	}
}
